#include "ChestFortify.h"
#include "Expand/PluginsManager.h"
#include "Expand/Plugins/AuthPlugin.h"

#include "Managers/BlocksManager.h"
#include "Expand/EventManager.h"
#include "Blocks/ChestBlock.h"
#include "Blocks/MagnetBlock.h"

#include "PlayerEvent.h"
#include "GameSingleton.h"
#include "Log.h"

#include <fstream>
#include <cfloat>

namespace CXHGT
{
    static const std::string titleText = "ChestFortify";


    ChestFortify::ChestFortify() : lockBlockValue(MagnetBlock::Index()), addFortifyCount(100)
    {
        m_playerEvent = new PlayerEvent(this);
        GameSingleton::eventManager->addEvent<IInventoryEvent>(m_playerEvent);
        GameSingleton::eventManager->addEvent<IInventoryOpenEvent>(m_playerEvent);
        GameSingleton::eventManager->addEvent<IPlayerEvent>(m_playerEvent);
    }

    const std::string &ChestFortify::getPluginName()
    {
        static const std::string pluginName = "箱子强化插件";
        return pluginName;
    }

    const std::string &ChestFortify::getIntroduce()
    {
        static const std::string introduce = "\n磁铁锁箱子，可以多次加强锁，锁完箱子后其他玩家想要破坏需要挖掉箱子（磁铁数*100）下才行";
        return introduce;
    }

    uint32_t ChestFortify::getUseAuthLevel()
    {
        return 100;
    }

    AuthDisplayType ChestFortify::getDisplayType()
    {
        return AuthDisplayType::Authority;
    }

    void ChestFortify::processCmd(ChatObj &chatObj, std::vector<std::string> &cmdDataVec) {}


    bool ChestFortify::isOwner(const Point3& point, const GameGuid& userGuid)
    {
        if (m_authPlugin->getLevelByGuid(userGuid) >= 100)
        {
            return true;
        }

        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_chestFortifyMap.find(point);
        if (it != m_chestFortifyMap.end())
        {
            if (it->second.userGuid != userGuid)
            {
                return false;
            }
        }
        return true;
    }

    bool ChestFortify::breakChest(const Point3& point, const GameGuid& userGuid)
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_chestFortifyMap.find(point);
        if (it != m_chestFortifyMap.end())
        {
            if (it->second.userGuid != userGuid && m_authPlugin->getLevelByGuid(userGuid) < 100)
            {
                if (it->second.fortifyCount > 0)
                {
                    it->second.fortifyCount--;
                    return false;
                }
            }
            m_chestFortifyMap.erase(it);
        }
        return true;
    }

    uint32_t ChestFortify::addChestFortify(const Point3& point, const GameGuid& userGuid, uint32_t fortifyCount)
    {
        if (fortifyCount == 0)
        {
            return 0;
        }
        uint32_t returnValue = 0;

        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_chestFortifyMap.find(point);
        if (it != m_chestFortifyMap.end())
        {
            if (it->second.userGuid != userGuid)
            {
                return 0;
            }
            it->second.fortifyCount += fortifyCount;
            returnValue = it->second.fortifyCount;
        }
        else
        {
            m_chestFortifyMap[point] = ChestFortifyData{userGuid, fortifyCount};
            returnValue = fortifyCount;
        }
        return returnValue;
    }

    void ChestFortify::load()
    {
        m_authPlugin = GameSingleton::pluginsManager->findPlugin<AuthPlugin>();


        Block *block = GameSingleton::blocksManager->blocks[ChestBlock::Index()];
        block->ProjectileResilience = 1.0f;         // 不会被击毁
        block->ExplosionResilience = FLT_MAX;       // 不会被炸毁
        block->IsFluidBlocker = true;               // 不会被流体冲掉
        block->FireDuration = 0.0f;                 // 不会着火

        std::ifstream stream;
        stream.open("./Plugins/ChestFortify/ChestFortify.json");
        if(stream.is_open())
        {
            nlohmann::json jsonData;
            stream >> jsonData;

            lockBlockValue = jsonData["lockBlockValue"].get<int32_t>();
            addFortifyCount = jsonData["addFortifyCount"].get<uint32_t>();
            m_chestFortifyMap = jsonData["data"].get<std::map<Point3, ChestFortifyData>>();
        }
        stream.close();
    }

    void ChestFortify::save()
    {
        const std::string pluginDataPath = "./Plugins/ChestFortify";
        if(std::filesystem::exists(pluginDataPath) == false)
        {
            if(std::filesystem::create_directories(pluginDataPath) == false)
            {
                throw std::runtime_error("检测不到起床战争数据文件夹，并且无法创建新的 强化箱子 数据文件夹");
            }
        }

        m_mapMutex.lock();

        nlohmann::json jsonData = {
            { "lockBlockValue", lockBlockValue },
            { "addFortifyCount", addFortifyCount },
            { "data", m_chestFortifyMap }};

        m_mapMutex.unlock();

        Utils::SaveTextFile(fmt::format("{}/ChestFortify.json", pluginDataPath), jsonData.dump());
    }

    void ChestFortify::getCmds(std::vector<std::string> &cmdVec){}

} // namespace PocketSurvival


using namespace PocketSurvival;

extern "C" void initialize()
{
    GameSingleton::pluginsManager->registerPlugin<CXHGT::ChestFortify>();
    Log::Info("成功加载 ChestFortify 插件");
}